1 /* 2 * Collie - An asynchronous event-driven network framework using Dlang development 3 * 4 * Copyright (C) 2015-2017 Shanghai Putao Technology Co., Ltd 5 * 6 * Developer: putao's Dlang team 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module collie.bootstrap.serversslconfig; 13 14 import std.string; 15 16 //import kiss.net; 17 18 version(USE_SSL) 19 { 20 public import deimos.openssl.ssl; 21 public import deimos.openssl.bio; 22 } 23 else 24 { 25 alias SSL_CTX = int; 26 } 27 28 enum SSLMode 29 { 30 SSLv2v3 = 3, 31 TLSv1 = 4, 32 TLSv1_1 = 5, 33 TLSv1_2 = 6 34 } 35 36 class ServerSSLConfig 37 { 38 this(SSLMode mode) 39 { 40 _mode = mode; 41 } 42 43 SSL_CTX* generateSSLCtx() 44 { 45 if(_ctx) 46 return _ctx; 47 version(USE_SSL) 48 { 49 final switch (_mode) 50 { 51 case SSLMode.SSLv2v3: 52 _ctx = SSL_CTX_new(SSLv23_method()); 53 break; 54 case SSLMode.TLSv1: 55 _ctx = SSL_CTX_new(TLSv1_method()); 56 break; 57 case SSLMode.TLSv1_1: 58 _ctx = SSL_CTX_new(TLSv1_1_method()); 59 break; 60 case SSLMode.TLSv1_2: 61 _ctx = SSL_CTX_new(TLSv1_2_method()); 62 break; 63 } 64 if (_ctx is null) 65 return null; 66 if (SSL_CTX_use_certificate_file(_ctx, toStringz(_certificateFile), SSL_FILETYPE_PEM) < 0) 67 { 68 error("SSL_CTX_use_certificate_file failed ! file : ", _certificateFile); 69 SSL_CTX_free(_ctx); 70 return null; 71 } 72 if (SSL_CTX_use_PrivateKey_file(_ctx, toStringz(_privateKeyFile), SSL_FILETYPE_PEM) < 0) 73 { 74 error("SSL_CTX_use_PrivateKey_file failed! file : ", _privateKeyFile); 75 SSL_CTX_free(_ctx); 76 return null; 77 } 78 if (SSL_CTX_check_private_key(_ctx) < 0) 79 { 80 error("SSL_CTX_check_private_key failed"); 81 SSL_CTX_free(_ctx); 82 return null; 83 } 84 } 85 return _ctx; 86 } 87 88 @property certificateFile(string file) 89 { 90 _certificateFile = file; 91 } 92 93 @property certificateFile() 94 { 95 return _certificateFile; 96 } 97 98 @property privateKeyFile(string file) 99 { 100 _privateKeyFile = file; 101 } 102 103 @property privateKeyFile() 104 { 105 return _privateKeyFile; 106 } 107 108 @property cipherList(string cliper) 109 { 110 _cipherList = cliper; 111 } 112 113 @property cipherList() 114 { 115 return _cipherList; 116 } 117 118 @property sslMode() 119 { 120 return _mode; 121 } 122 123 private: 124 string _certificateFile; 125 string _privateKeyFile; 126 string _cipherList; 127 SSLMode _mode; 128 SSL_CTX* _ctx = null; 129 } 130 131 version(USE_SSL) 132 { 133 import core.sync.mutex; 134 import core.thread; 135 136 shared static this() 137 { 138 SSL_load_error_strings(); 139 SSL_library_init(); 140 sslmutex = new Mutex[CRYPTO_num_locks()]; 141 for (uint i = 0; i < sslmutex.length; ++i) 142 { 143 sslmutex[i] = new Mutex(); 144 } 145 static if (OPENSSL_VERSION_NUMBER > 0x10000000L) 146 { 147 CRYPTO_THREADID_set_callback(&threadid_function); 148 } 149 else 150 { 151 CRYPTO_set_id_callback(&id_function); 152 } 153 CRYPTO_set_locking_callback(&ssl_lock_callback); 154 } 155 156 shared static ~this() 157 { 158 static if (OPENSSL_VERSION_NUMBER > 0x10000000L) 159 { 160 CRYPTO_THREADID_set_callback(null); 161 } 162 else 163 { 164 CRYPTO_set_id_callback(null); 165 } 166 CRYPTO_set_locking_callback(null); 167 } 168 169 private: 170 __gshared Mutex[] sslmutex; 171 172 extern (C): 173 pragma(inline, true) ulong id_function() 174 { 175 return cast(ulong)(Thread.getThis.id); 176 } 177 178 void threadid_function(CRYPTO_THREADID* id) 179 { 180 version (Windows) 181 { 182 CRYPTO_THREADID_set_numeric(id, cast(uint) id_function()); 183 } 184 else 185 { 186 CRYPTO_THREADID_set_numeric(id, id_function()); 187 } 188 } 189 190 void ssl_lock_callback(int mode, int type, const(char)* file, int line) 191 { 192 if (mode & CRYPTO_LOCK) 193 { 194 sslmutex[type].lock(); 195 } 196 else 197 { 198 sslmutex[type].unlock(); 199 } 200 } 201 }